package model.beans;

import java.io.Serializable;
import java.security.InvalidParameterException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import util.ProjectConstants;

/**
 * ShoppingCartBean process shopping cart logic
 * @author Frank
 *
 */
public class ShoppingCartBean implements Serializable{
	
	private static final long serialVersionUID = 7072687518913334647L;

	private Map<String, ShoppingCartItemBean> itemsMap;
	private List<ShoppingCartItemBean> itemList;
	private double total;
	private double shippingFee;
	private double HST;
	private double grandTotal;
	private int numOfItems;
	
	
	/**
	 * Default Constructor, instantiate the variables
	 */
	public ShoppingCartBean(){
		this.itemsMap = new HashMap<String, ShoppingCartItemBean>();
		this.itemList = new ArrayList<ShoppingCartItemBean>();		
		this.total = 0.0;
		this.shippingFee = ProjectConstants.SHIPPINGFEE;
		this.HST = 0.0;
		this.grandTotal = 0.0;
		this.numOfItems = 0;
	}	

	/**
	 * @return the total
	 */
	public double getTotal() {
		double sum = 0;
		DecimalFormat df = new DecimalFormat("#0.00");
		
		for ( ShoppingCartItemBean sci : this.getItemList()){
			sum += sci.getQuantity() * sci.getItem().getPrice();
		}	
		return Double.valueOf(df.format(sum));	
	}

	/**
	 * @return the itemList
	 */
	public List<ShoppingCartItemBean> getItemList(){	
		return new ArrayList<ShoppingCartItemBean>(itemsMap.values());
	}
	
	/**
	 * @param itemList the itemList to set
	 */
	public void setItemList(List<ShoppingCartItemBean> itemList){
		this.itemList = itemList;
	}

	/**
	 * @return the shippingFee
	 */
	public double getShippingFee() {
		DecimalFormat df = new DecimalFormat("#0.00");
		if(this.getTotal() < 100){
			this.shippingFee = ProjectConstants.SHIPPINGFEE;
		}
		else{
			this.shippingFee = 0;
		}
		return Double.valueOf(df.format(this.shippingFee));
	}
	
	/**
	 * @return the HST
	 */
	public double getHST() {
		DecimalFormat df = new DecimalFormat("#0.00");
		double hst = (this.getTotal() + this.getShippingFee()) * ProjectConstants.HST;
		return Double.valueOf(df.format(hst));
	}

	/**
	 * @return the grandTotal
	 */
	public double getGrandTotal() {
		DecimalFormat df = new DecimalFormat("#0.00");
		double grandTotal = this.getTotal() + this.getShippingFee() + this.getHST();
		return Double.valueOf(df.format(grandTotal));
	}	
	
	/**
	 * @return the numOfItems
	 */
	public int getNumOfItems(){
		return this.itemsMap.size();
	}


	/**
	 * @return the itemsMap
	 */
	public Map<String, ShoppingCartItemBean> getItemsMap(){
		return itemsMap;
	}
	/**
	 * @param itemsMap the itemsMap to set
	 */
	public void setItemsMap(Map<String, ShoppingCartItemBean> itemsMap){
		this.itemsMap = itemsMap;
	}
	
	/**
	 * validate item quantity
	 * @param qty
	 * @return
	 */
	public int validateItemQuantity(String qty)	{		
		int temp = Integer.parseInt(qty);
		if ( temp <= 0 )  throw new InvalidParameterException();
		return temp;
	}
	
	
	public void addItem(ShoppingCartItemBean item)
	{
		String itemNumber = item.getItem().getNumber();
		
		// if item exist in the cart, increase the quantity, otherwise add item to the cart
		if ( itemsMap.containsKey(itemNumber))	{
			int qty = itemsMap.get(itemNumber).getQuantity();			
			itemsMap.get(itemNumber).setQuantity( qty + item.getQuantity());
		}
		else{
			// if no such item in the cart, add this item to the cart
			itemsMap.put(itemNumber, item);
			this.setItemList(new ArrayList<ShoppingCartItemBean>(itemsMap.values()));			
		}		
	}
	
	public synchronized void updateItem(String itemNumber, Integer qty)	{
		
		// if qty == 0, remove the item from the cart, otherwise, update the quantity of the item,
		if ( qty != 0 )	{
			itemsMap.get(itemNumber).setQuantity(qty);	
		}
		else{
			itemsMap.remove(itemNumber);
		}		
	}
	
	public synchronized void updateCart(Map<String, Integer> map){
		for (String key: this.itemsMap.keySet()){
			if ( map.containsKey(key)){
				
				// get the new item quantity
				int qty = (Integer)map.get(key);
	
				// remove item if qty is 0
				if ( qty == 0) {
					this.itemsMap.remove(key);
				}
				else  // update the quantity with the new one
				{
					this.itemsMap.get(key).setQuantity(qty); 
				}
			}
		}
	}
}
